#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "StoreSymEntry.h"
#include "SymEntry.h"

StoreSymEntry::StoreSymEntry(size_t initLength) :
		length(initLength) {
	store = (SymEntry*) new char[length * sizeof(SymEntry)];

	lastBlock = store;
	lastBlockSize = length;
	*((int**) store) = 0;

	sizeFree = lastBlockSize - sizeof(SymEntry);
	startFreeSpace = (SymEntry*) ((store + sizeof(SymEntry)));
}

StoreSymEntry::~StoreSymEntry() {
	int* next = *(int**) store;
	int* current = (int*) store;

	delete[] (char*) current;
	current = next;
	while (current != 0) {
		next = *(int**) current;
		delete[] (char*) current;
		current = next;
	}
}

void StoreSymEntry::expand() {
	lastBlockSize *= 2;
	SymEntry* newBlock = (SymEntry*) new char[lastBlockSize * sizeof(SymEntry)];

	writeNextBlockPosition(newBlock); // write pointer to new block

	lastBlock = newBlock;
	// skip over the pointer we just wrote
	startFreeSpace = newBlock + sizeof(SymEntry*);
	*((SymEntry**) lastBlock) = 0;
	sizeFree = lastBlockSize - sizeof(SymEntry*);
}

void StoreSymEntry::writeNextBlockPosition(SymEntry* next) {
	*((SymEntry**) lastBlock) = next;
}

SymEntry* StoreSymEntry::add(SymInfo* info, char* lexem) {
	SymEntry* oldStartFreeSpace = startFreeSpace;
	startFreeSpace->Set(info, lexem);

	--sizeFree;
	if (sizeFree == 0) {
		expand();
	} else {
		++startFreeSpace;
	}
	return oldStartFreeSpace;
}
